package cn.com.blueInfo.bpm.system.repository.impl;

import cn.com.blueInfo.bpm.common.entity.BaseEntity;
import cn.com.blueInfo.bpm.common.enums.BaseDeleted;
import cn.com.blueInfo.bpm.common.repository.BaseRepository;
import cn.com.blueInfo.bpm.system.entity.Menu;
import cn.com.blueInfo.bpm.system.enums.MenuType;
import cn.com.blueInfo.bpm.system.mapper.MenuMapper;
import cn.com.blueInfo.bpm.system.repository.MenuRepository;
import cn.com.blueInfo.bpm.system.request.MenuDTO;
import cn.com.blueInfo.core.entity.CurrentLoginUserInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* 菜单表 数据服务实现类
* @author suxch
* @since 2025-09-01 19:17:41
*/
@Log4j2
@Service
public class MenuRepositoryImpl
        extends ServiceImpl<MenuMapper, Menu>
        implements MenuRepository, BaseRepository<Menu, MenuDTO.QueryDTO> {

    @Autowired
    private CurrentLoginUserInfo currentLoginUserInfo;

    /**
     * 提供获取 CurrentLoginUserInfo 的方法（由实现类提供，避免接口中注入）
     * @return CurrentLoginUserInfo
     */
    @Override
    public CurrentLoginUserInfo getCurrentLoginUserInfo() {
        return currentLoginUserInfo;
    }

    /**
    * 新增菜单
    * @param menu 菜单参数
    */
    @Override
    public Integer createMenu(Menu menu) {
        return sqlExecuteResult(save(menu));
    }

    /**
     * 批量新增菜单
     * @param menuList 菜单参数列表
     */
    @Override
    public Integer batchCreateMenu(List<Menu> menuList) {
        return sqlExecuteResult(saveBatch(menuList), menuList.size());
    }

    /**
    * 删除菜单
    * @param menuId 菜单ID
    */
    @Override
    public Integer deleteMenu(Long menuId) {
        Menu menu = new Menu();
        menu.setId(menuId);
        menu.setDeleted(BaseDeleted.DELETED);
        return sqlExecuteResult(removeById(menu));
    }

    /**
     * 批量删除菜单
     * @param menuIdList 菜单ID列表
     */
    @Override
    public Integer batchDeleteMenu(List<Long> menuIdList) {
        List<Menu> menuList = new ArrayList<>();
        for (Long menuId : menuIdList) {
            Menu menu = new Menu();
            menu.setId(menuId);
            menu.setDeleted(BaseDeleted.DELETED);
            menuList.add(menu);
        }
        return sqlExecuteResult(removeBatchByIds(menuList), menuList.size());
    }

    /**
    * 更新部分菜单
    * @param menu 菜单参数
    */
    @Override
    public Integer updateMenuPartial(Menu menu) {
        validateUpdateId(menu.getId());
        LambdaUpdateWrapper<Menu> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Menu::getId, menu.getId());
        return sqlExecuteResult(update(updateWrapper));
    }

    /**
    * 更新全部菜单
    * @param menu 菜单参数
    */
    @Override
    public Integer updateMenu(Menu menu) {
        validateUpdateId(menu.getId());
        return sqlExecuteResult(updateById(menu));
    }

    /**
    * 查询一条菜单
    * @param menuId 菜单ID
    */
    @Override
    public Menu getMenuById(Long menuId) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getId, menuId);
        return getOne(queryWrapper);
    }

    /**
    * 分页查询菜单
    * @param menuQueryDTO 菜单参数
    */
    @Override
    public Page<Menu> getMenuPage(MenuDTO.QueryDTO menuQueryDTO) {
        Page<Menu> menuPage = new Page<>(
                menuQueryDTO.getPage(), menuQueryDTO.getSize());
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper(queryWrapper, menuQueryDTO);
        queryWrapper.orderByAsc(Menu::getOrderNumber);

        BaseDeleted deleted = menuQueryDTO.getDeleted();
        if (ObjectUtils.isNotEmpty(deleted) && deleted.equals(BaseDeleted.DELETED)) {
            return baseMapper.selectDeletePage(menuPage, queryWrapper);
        } else {
            return page(menuPage, queryWrapper);
        }
    }

    /**
     * 根据条件查询 菜单 数量
     * @param menuQueryDTO 菜单参数
     */
    @Override
    public Long getMenuCount(MenuDTO.QueryDTO menuQueryDTO) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper(queryWrapper, menuQueryDTO);

        BaseDeleted deleted = menuQueryDTO.getDeleted();
        if (ObjectUtils.isNotEmpty(deleted) && deleted.equals(BaseDeleted.DELETED)) {
            return baseMapper.selectDeleteCount(queryWrapper);
        } else {
            return count(queryWrapper);
        }
    }

    /**
     * 根据条件查询 菜单
     * @param menuQueryDTO 菜单参数
     */
    @Override
    public List<Menu> getMenuList(MenuDTO.QueryDTO menuQueryDTO) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper(queryWrapper, menuQueryDTO);
        queryWrapper.orderByAsc(Menu::getOrderNumber);

        BaseDeleted deleted = menuQueryDTO.getDeleted();
        if (ObjectUtils.isNotEmpty(deleted) && deleted.equals(BaseDeleted.DELETED)) {
            return baseMapper.selectDeleteList(queryWrapper);
        } else {
            return list(queryWrapper);
        }
    }

    private void queryWrapper(LambdaQueryWrapper<Menu> queryWrapper, MenuDTO.QueryDTO menuQueryDTO) {

        String menuName = menuQueryDTO.getMenuName();
        queryWrapper.eq(StringUtils.isNotBlank(menuName), Menu::getMenuName, menuName);

        Long parentId = menuQueryDTO.getParentId();
        queryWrapper.eq(ObjectUtils.isNotEmpty(parentId), Menu::getParentId, parentId);

        String routePath = menuQueryDTO.getRoutePath();
        queryWrapper.eq(StringUtils.isNotBlank(routePath), Menu::getRoutePath, routePath);

        String component = menuQueryDTO.getComponent();
        queryWrapper.eq(StringUtils.isNotBlank(component), Menu::getComponent, component);

        String icon = menuQueryDTO.getIcon();
        queryWrapper.eq(StringUtils.isNotBlank(icon), Menu::getIcon, icon);

        MenuType menuType = menuQueryDTO.getMenuType();
        queryWrapper.eq(ObjectUtils.isNotEmpty(menuType), Menu::getMenuType, menuType);

        String permissionKey = menuQueryDTO.getPermissionKey();
        queryWrapper.eq(StringUtils.isNotBlank(permissionKey), Menu::getPermissionKey, permissionKey);

        addQueryWrapper(queryWrapper, menuQueryDTO, getCommonColumn());

    }

    private Map<String, SFunction<Menu, ?>> getCommonColumn() {
        return BaseEntity.getCommonColumn(
                Menu::getOrderNumber,
                Menu::getTenantId,
                Menu::getApplicationId,
                Menu::getStatus,
                Menu::getDeleted,
                Menu::getDeleteUserId,
                Menu::getDeleteTime,
                Menu::getRemark,
                Menu::getCreateUserId,
                Menu::getCreateTime,
                Menu::getUpdateUserId,
                Menu::getUpdateTime,
                Menu::getExtend1,
                Menu::getExtend2,
                Menu::getExtend3);
    }

}
